<?php

namespace App\Domain\Customer\Services;

use App\Exceptions\JsonResponse\JsonResponseException;
use App\Service\BaseUtil\ThirdApiRequestConstant;
use App\Service\BaseUtil\ThirdApiRequestInterface;
use Illuminate\Support\Facades\Cache;

class VerificationCodeService
{

    /**
     * @var VerificationCodeDes
     */
    private $verificationCodeDes;

    /**
     * @var ThirdApiRequestInterface
     */
    private $thirdApiRequest;
    /**
     * @var string
     */
    private $url;

    /**
     * VerificationCodeService constructor.
     * @param VerificationCodeDes $verificationCodeDes
     * @param ThirdApiRequestInterface $thirdApiRequest
     */
    public function __construct(VerificationCodeDes $verificationCodeDes, ThirdApiRequestInterface $thirdApiRequest)
    {

        $this->verificationCodeDes = $verificationCodeDes;
        $this->thirdApiRequest = $thirdApiRequest;
        $this->url = config("sys.message_url");
    }

    /**
     * 创建登录验证码并发送短信
     * @param string $phone
     * @return string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function create(string $phone)
    {
        $code = $this->sendMessage($phone);
        $this->setCode($code, $phone);
        return $code;
    }

    /**
     * 发松短信
     * @param string $phone
     * @return string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function sendMessage(string $phone): string
    {
        $code = mt_rand(111111, 999999);
        $data = [
            "signName" => "渐健家庭医生",
            "msgParmCode" => json_encode([
                'code' => (string) $code,
                'time' => "5分钟",
                'action' => "登录",
            ],JSON_UNESCAPED_UNICODE),
            "phone" => $phone,
            "smsCode" => "SMS_107920044",
            "time" => bcmul(microtime(true), 1000),
        ];
        $sendData["signature"] = $this->verificationCodeDes->encryptDes(json_encode($data,JSON_UNESCAPED_UNICODE));
        $request = $this->thirdApiRequest->request("POST",$this->url,ThirdApiRequestConstant::X_WWW_FORM_URLENCODED,$sendData,[]);
        $response = json_decode($request,true);
        if($response["code"] != 0){
            throw new JsonResponseException("验证码发送失败：".$response["msg"]);
        }
        return $code;
    }

    /**
     * 设置验证码缓存
     * @param string $code
     * @param string $phone
     */
    private function setCode(string $code, string $phone)
    {
        $key = $this->getKey($phone);
        Cache::put($key, $code, 300);
    }

    /**
     * @param string $phone
     * @return string
     */
    private function getKey(string $phone)
    {
        return $phone . "_login_code";
    }

    /**
     * @param string $phone
     * @param string $verificationCode
     */
    public function validateOrFail(string $phone, string $verificationCode)
    {
        if (!$this->validate($phone, $verificationCode)) {
            throw new JsonResponseException("验证码错误");
        }
    }

    /**
     * 验证短信验证码是否正确
     * @param string $phone
     * @param string $code
     * @return bool
     */
    public function validate(string $phone, string $code)
    {
        $trueCode = $this->getCode($phone);
        if (!$trueCode) {
            throw new JsonResponseException("验证码已过期");
        }
        return $code == $trueCode;
    }

    /**
     * 获取登录验证码
     * @param string $phone
     * @return string
     */
    private function getCode(string $phone)
    {
        $key = $this->getKey($phone);
        if (Cache::has($key)) {
            return Cache::get($key);
        } else {
            return "";
        }
    }

}
